package com.coin.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.*;
import com.coin.domain.SysMenu;
import com.coin.feignclient.*;
import com.coin.model.LoginResult;
import com.coin.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.jwt.*;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Auther: 李 力
 * @Date: 2025/5/26
 * @Description: com.coin.service.impl
 * @version: 1.0
 */
@Service
@Slf4j
public class SysLoginServiceImpl implements SysLoginService {

    @Autowired
    private OAuth2FeignClient oAuth2FeignClient;

    @Value("${basic.token:Basic Y29pbi1hcGk6Y29pbi1zZWNyZXQ=}")
    private String basic;

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * @Description: 管理员登录接口
     * @Author: 李 力
     * @Date: 2025/5/26
     * @Param: 用户名和密码
     * @return: LoginResult
     */
    @Override
    public LoginResult login(String username, String password) {
        if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
            throw new RuntimeException("参数为空");
        }
        //1.获取token
        ResponseEntity<JwtToken> tokenResponseEntity = oAuth2FeignClient.getToken("password", username, password, "admin_type", basic);
        if (tokenResponseEntity == null) {
            throw new RuntimeException("获取token响应为null");
        }
        if (tokenResponseEntity.getStatusCode() != HttpStatus.OK) {
            throw new RuntimeException("获取token失败");
        }
        JwtToken jwtToken = tokenResponseEntity.getBody();
        if (jwtToken == null) {
            throw new RuntimeException("获取token为null");
        }
        log.info("远程调用授权服务器，获取的token为{}", JSONUtil.toJsonStr(jwtToken));
        //2.解析token
        String token = jwtToken.getAccessToken();
        Jwt jwt = JwtHelper.decode(token);
        String claims = jwt.getClaims();
        JSONObject jsonObject = JSONUtil.parseObj(claims);
        //这个地方实际是userId
        Long userId = jsonObject.get("user_name", Long.class);
        //2.获取菜单数据
        List<SysMenu> menuList = sysMenuService.getMenusByUserId(userId);
        //3.获取权限数据: 这个地方不需要查询了,jwt里面放了的
        JSONArray authoritiesJsonArray = jsonObject.getJSONArray("authorities");
        List<SimpleGrantedAuthority> authorities = authoritiesJsonArray.stream() // 组装我们的权限数据
                .map(authorityJson -> new SimpleGrantedAuthority(authorityJson.toString())).collect(Collectors.toList());
        //4.将token放在redis里面
        //生成权限信息对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, token, authorities);
        //把权限信息对象存入到权限上下文中
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        redisTemplate.opsForValue().set(token, "", jwtToken.getExpiresIn(), TimeUnit.SECONDS);
        return new LoginResult(jwtToken.getTokenType() + " " + token, menuList, authorities);
    }
}
